package com.gxc.array;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 39. 组合总和
 * 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ，
 * 找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ，并以列表形式返回。
 * 你可以按 任意顺序 返回这些组合。
 *
 * candidates 中的 同一个 数字可以 无限制重复被选取 。
 * 如果至少一个数字的被选数量不同，则两种组合是不同的。
 *
 * 对于给定的输入，保证和为 target 的不同组合数少于 150 个。
 */
public class CombinationSum {

    public static void main(String[] args) {
        List<List<Integer>> list = handle(new int[]{2,3,5}, 8);
        System.out.println("");
    }

    public static List<List<Integer>> handle(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> res = new ArrayList<>();
        for (int i = 0; i < candidates.length; i++) {
            List<Integer> list = new ArrayList<>();
            list.add(candidates[i]);
            int sum = recursion(candidates, target - candidates[i], list, i, res);
        }
        return res;
    }

    public static int recursion(int[] candidates, int target, List<Integer> list, int start, List<List<Integer>> sum) {
        if (target == 0) {
            sum.add(new ArrayList<>(list));
            return 1;
        } else if (target < 0) return 0;

        int res = 0;
        for (int i = start; i < candidates.length; i++) {
            list.add(candidates[i]);
            res = recursion(candidates, target - candidates[i], list, i, sum);
            //回滚
            list.remove(list.size() - 1);
        }
        return res;
    }

    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> ans = new ArrayList<List<Integer>>();
            List<Integer> combine = new ArrayList<Integer>();
            dfs(candidates, target, ans, combine, 0);
            return ans;
        }

        public void dfs(int[] candidates, int target, List<List<Integer>> ans, List<Integer> combine, int idx) {
            if (idx == candidates.length) {
                return;
            }
            if (target == 0) {
                ans.add(new ArrayList<Integer>(combine));
                return;
            }
            // 直接跳过
            dfs(candidates, target, ans, combine, idx + 1);
            // 选择当前数
            if (target - candidates[idx] >= 0) {
                combine.add(candidates[idx]);
                dfs(candidates, target - candidates[idx], ans, combine, idx);
                combine.remove(combine.size() - 1);
            }
        }
    }

}
